package cn.iocoder.yudao.module.pay.bill.service;

import cn.iocoder.yudao.framework.business.basic.dao.query.CoreLambdaQueryWrapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.api.pay.bill.enums.BillCategoryEnum;
import cn.iocoder.yudao.module.api.pay.bill.enums.BillModeEnum;
import cn.iocoder.yudao.module.api.pay.bill.enums.BillTypeEnum;
import cn.iocoder.yudao.module.pay.bill.convert.PayBillConvert;
import cn.iocoder.yudao.module.pay.bill.dal.dataobject.PayBillDO;
import cn.iocoder.yudao.module.pay.bill.dal.mysql.PayBillMapper;
import cn.iocoder.yudao.module.pay.bill.vo.AppPayBillPageReqVO;
import cn.iocoder.yudao.module.pay.bill.vo.AppPayBillRespVO;
import cn.iocoder.yudao.module.pay.bill.vo.PayBillPageReqVO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

/**
 * 账单 Service 实现类
 *
 * @author yshop
 * @author 山野羡民
 */
@Service
@Validated
public class PayBillServiceImpl extends ServiceImpl<PayBillMapper, PayBillDO> implements PayBillService {

    @Resource
    private PayBillMapper payBillMapper;

    @Override
    public PageResult<PayBillDO> getBillPage(PayBillPageReqVO pageReqVO) {
        return payBillMapper.selectPage(pageReqVO);
    }

    @Override
    public boolean exists(Long userId, String relateId) {
        PayBillDO aDo = payBillMapper.selectOne(PayBillDO::getUserId, userId, PayBillDO::getRelateId, relateId);
        return aDo != null;
    }

    @Async
    @Override
    public void expendAsync(Long userId, BillCategoryEnum category, BillTypeEnum type, Double number, String mark, String relateId, String extendField) {
        number = -1 * Math.abs(number); // 确保剩余的资产值是负数累加
        create(BillModeEnum.EXPEND, userId, category, type, number, mark, relateId, extendField);
    }


    @Async
    @Override
    public void incomeAsync(Long userId, BillCategoryEnum category, BillTypeEnum type, Double number, String mark, String relateId, String extendField) {
        number = Math.abs(number); // 确保剩余的资产值是正数累加
        create(BillModeEnum.INCOME, userId, category, type, number, mark, relateId, extendField);
    }

    private void create(BillModeEnum mode, Long userId, BillCategoryEnum category, BillTypeEnum type, double number, String mark, String relateId, String extendField) {
        double balance = calculateBalance(userId, category, number);
        PayBillDO payBillDO = new PayBillDO();
        payBillDO.setUserId(userId);
        payBillDO.setMode(mode.getValue());
        payBillDO.setTitle(type.getName());
        payBillDO.setCategory(category.getCode());
        payBillDO.setType(type.getCode());
        payBillDO.setNumber(number);
        payBillDO.setBalance(balance);
        payBillDO.setMark(mark);
        payBillDO.setRelateId(relateId);
        payBillDO.setExtendField(extendField);
        payBillMapper.insert(payBillDO);
    }

    private double calculateBalance(Long userId, BillCategoryEnum category, double number) {
        CoreLambdaQueryWrapper<PayBillDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.select(PayBillDO::getBalance);
        wrapper.eq(PayBillDO::getUserId, userId);
        wrapper.eq(PayBillDO::getCategory, category.getCode());
        wrapper.orderByDesc(PayBillDO::getId);
        wrapper.limitN(1);
        PayBillDO payBillDO = payBillMapper.selectOne(wrapper);
        if (payBillDO == null || payBillDO.getBalance() == null || payBillDO.getBalance() <= 0) {
            return number;
        }
        return payBillDO.getBalance() + number;
    }

    @Override
    public PageResult<AppPayBillRespVO> getBillPage(Long userId, AppPayBillPageReqVO reqVO) {
        PageResult<PayBillDO> page = payBillMapper.selectPage(userId, reqVO);
        return PayBillConvert.INSTANCE.convertPage2(page);
    }

    @Override
    public Double getNumberSum(Long userId, AppPayBillPageReqVO reqVO) {
        return payBillMapper.selectNumberSum(userId, reqVO);
    }

    @Override
    public Double getInNumberSum(Long userId, AppPayBillPageReqVO reqVO) {
        return payBillMapper.selectInNumberSum(userId, reqVO);
    }

    @Override
    public Double getOutNumberSum(Long userId, AppPayBillPageReqVO reqVO) {
        return payBillMapper.selectOutNumberSum(userId, reqVO);
    }

    @Override
    public PayBillDO selectByRelateId(String relateId) {
        return payBillMapper.selectOne(PayBillDO::getRelateId, relateId);
    }

}
